#include "TaskQueue.h"

TaskQueue::TaskQueue(size_t capa)
: _capacity(capa)
, _que()
, _mutex()
, _notEmpty()
, _notFull()
, _flag(true)
{
}

TaskQueue::~TaskQueue()
{

}

//生产数据与消费数据
void TaskQueue::push(ElemType ptask)
{
    //1、先上锁
    unique_lock<mutex> ul(_mutex);//上锁
    //2、判满
    while(full())//为了解决虚假唤醒的问题，可以将if改为while循环
    {
        //2.1、如果发现仓库是满的，睡眠
        //wait函数的底层会：先解锁（释放锁），然后睡眠(解锁与睡眠是原子的)
        //在被唤醒之后，要：先抢锁、最后返回(抢到才能返回)
        _notFull.wait(ul);
    }
    //2.2、如果不满，就可以将数据存放在仓库中（也就是数据成员queue中）
    //然后唤醒消费者
    _que.push(ptask);
    _notEmpty.notify_one();
}

/* TaskQueue::ElemType TaskQueue::pop() */
ElemType TaskQueue::pop()
{
    unique_lock<mutex> ul(_mutex);//上锁
    while(empty() && _flag)
    {
        _notEmpty.wait(ul);
    }

    if(_flag)
    {
        ElemType tmp = _que.front();//获取元素
        _que.pop();//然后删除
        _notFull.notify_one();

        return tmp;
    }
    else
    {
        return nullptr;
    }
}

//判空与判满
bool TaskQueue::empty() const
{
    return 0 == _que.size();
}

bool TaskQueue::full() const
{
    return _capacity == _que.size();
}

void TaskQueue::wakeup()
{
    _flag = false;
    _notEmpty.notify_all();
}

